package com.gitee.sop.layui.adminserver.module.background.admin.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.gitee.sop.layui.adminserver.entrance.bo.ServiceContext;
import com.gitee.sop.layui.adminserver.module.background.admin.entity.SysUser;
import com.gitee.sop.layui.adminserver.module.background.admin.mapper.SysUserMapper;
import com.gitee.sop.layui.adminserver.module.background.admin.service.*;
import com.gitee.sop.layui.adminserver.module.background.admin.util.SysDataModifyLockUtil;
import com.gitee.sop.layui.adminserver.module.background.develop.service.SysFunctionRoleService;
import com.gitee.sop.layui.adminserver.module.base.error.ServiceInterruptionException;
import com.gitee.sop.layui.adminserver.module.base.util.AssertUtil;
import com.gitee.sop.layui.adminserver.module.base.util.Md5Util;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 后台管理员 服务实现类
 * </p>
 *
 * @author admin
 * @since 2019-11-13
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {
    @Lazy
    @Resource
    private SysUserMenuRoleRelationService sysUserMenuRoleRelationService;
    @Lazy
    @Resource
    private SysUserFunctionRoleRelationService sysUserFunctionRoleRelationService;
    @Lazy
    @Resource
    private SysFunctionRoleService sysFunctionRoleService;
    @Lazy
    @Resource
    private SysDataModifyLockService sysDataModifyLockService;
    @Lazy
    @Resource
    private SysUserApplicationRelationService sysUserApplicationRelationService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(SysUser sysUser) {
        SysUser old = baseMapper.selectOneByUserName1(sysUser.getUsername());
        AssertUtil.isNull(old, ServiceInterruptionException.fail(400, "用户名已存在" + sysUser.getUsername()));
        //密码加密
        String newPwd = Md5Util.getInstance().saltEncrypt(sysUser.getPassword());
        sysUser.init().setPassword(newPwd).setCreatedTime(new Date()).setCreatorUuid(ServiceContext.me().checkedUserAndGet(SysUser.class).getUuid());
        save(sysUser);
    }

    @Override
    public void deleteByUuid(String uuid) {
        sysDataModifyLockService.checkLocked(SysDataModifyLockUtil.generateKey(SysUser.class, uuid));

        SysUser old = this.baseMapper.selectOneByUuid(uuid);
        AssertUtil.notNull(old, ServiceInterruptionException.fail(400, "用户不存在"));
        SysUser sysUser = ServiceContext.me().checkedUserAndGet(SysUser.class);
        AssertUtil.isTrue(sysUser.getUuid().equals(old.getCreatorUuid()), ServiceInterruptionException.fail(400, "非法操作"));
        int childrenCount = this.baseMapper.selectCountBy(null, null, null, old.getUuid());
        AssertUtil.isTrue(childrenCount <= 0, ServiceInterruptionException.fail(400, "有关联子用户"));
        //删除菜单角色关联关系
        sysUserMenuRoleRelationService.removeByUserUuid(ServiceContext.me().getCurrentApplication().getAppId(), old.getUuid());
        //删除功能角色关联关系
        sysUserFunctionRoleRelationService.removeByUserUuid(old.getUuid());

        removeById(old.getId());
    }

    @Override
    public void setPassword(String oldPassword, String password) {
        SysUser sysUser = ServiceContext.me().checkedUserAndGet(SysUser.class);
        String dataKey = SysDataModifyLockUtil.generateKey(SysUser.class, sysUser.getUuid());
        sysDataModifyLockService.checkLocked(dataKey);

        boolean passwordChecked = Md5Util.getInstance().saltValid(oldPassword, sysUser.getPassword());
        if (!passwordChecked) {
            throw ServiceInterruptionException.fail(400, "旧密码错误");
        }
        String newPassword = Md5Util.getInstance().saltEncrypt(password);
        sysUser.setPassword(newPassword);

        updateById(sysUser);

        //更新数据锁中该管理员的密码，否则数据将无法解锁
        sysDataModifyLockService.updatePasswordByDataKey(dataKey, newPassword);
    }

    @Override
    public SysUser getOneByUsername(String username) {
        return baseMapper.selectOneByUserName1(username);
    }

    @Override
    public List<String> getFunctionRoleListByUuid(String uuid) {
        return sysFunctionRoleService.getFunctionRoleNameListByUserUuid(uuid);
    }

    @Override
    public Set<String> getPermissionUrls(String appId, String userUuid) {
        return sysUserMenuRoleRelationService.getPermissionUrl(appId, userUuid);
    }

    @Override
    public IPage<SysUser> getPageByUserUuid(int current, int size, String name, String username) {
        SysUser cur = ServiceContext.me().checkedUserAndGet(SysUser.class);

        IPage<SysUser> res = new Page<>(current, size);
        int total = this.baseMapper.selectCountBy(name, username, null, cur.getUuid());
        if (total > 0) {
            List<SysUser> list = this.baseMapper.selectPageBy(res.getCurrent(), res.getSize(), name, username, null, cur.getUuid());
            res.setRecords(list);
        }
        //加入自己，让其可修改权限
        if (current == 1) {
            List<SysUser> list = res.getRecords();
            if (list == null || list.isEmpty()) {
                res.setRecords(Arrays.asList(cur));
            } else {
                list.add(0, cur);
            }
        }
        res.setTotal(total);
        return res;
    }

    @Override
    public int getDisableMasterUserCount(String uuid) {
        return baseMapper.countDisableMasterUser(uuid);
    }

    @Override
    public void updateByUuid(SysUser modify) {
        SysUser sysUser = ServiceContext.me().checkedUserAndGet(SysUser.class);
        sysDataModifyLockService.checkLocked(SysDataModifyLockUtil.generateKey(SysUser.class, modify.getUuid()));
        if (sysUser.getUuid().equals(modify.getUuid()) && modify.getStatus().intValue() != sysUser.getStatus().intValue()) {
            throw ServiceInterruptionException.fail(400, "别作死!更新状态就不能登录了!");
        }
        Wrapper<SysUser> wrapper = new LambdaQueryWrapper<SysUser>().eq(SysUser::getUuid, modify.getUuid());
        super.update(modify, wrapper);
    }

    @Override
    public SysUser getOneByUuid(String uuid) {
        return this.baseMapper.selectOneByUuid(uuid);
    }
}
